<?php
declare (strict_types=1);

namespace addons\Builder\driver;

use addons\Builder\facade\Builder;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;
use think\facade\View;

class Table
{

    /**
     * @var array 模板变量
     */
    public $_vars = [
        'extra_js'       => '',          // 额外JS代码
        'extra_css'      => '',          // 额外CSS代码
        'extra_html'     => '',          // 额外HTML代码
        'columns'        => [],          // 表格列集合
        'right_buttons'  => [],          // 表格右侧按钮
        'top_buttons'    => [],          // 顶部栏按钮组[toolbar]
        'search'         => [],          // 搜索参数
        'js_url'         => [],          // 额外JS代码(文件名)
        'totalRow'       => 'false',     // 是否开启合计行
        'switch_tool'    => [],          // 开关绑定栏,
        'sort_tool'      => [],          // 排序绑定栏
        'extra_map'      => [],          // 额外查询条件
        'census'         => [],          // 额外统计条目
        'tableUniqueUrl' => ''
    ];


    public function fetch(string $template = '', bool $cache = false)
    {
        $tableCache = Builder::TableCache();
        //Table唯一key
        $key = $tableCache->getMethodUrl();
        //兼容手机端
        if (request()->isMobile()) {
            foreach ($this->_vars['columns'] as &$column) {
                unset($column['fixed']);
            }
            foreach ($this->_vars['right_buttons'] as &$column) {
                if (!empty($column['size'])) {
                    $column['width'] = '100%';
                }
            }
            foreach ($this->_vars['top_buttons'] as &$column) {
                if (!empty($column['size'])) {
                    $column['width'] = '100%';
                }
            }
        }
        //格式化右侧按钮
        foreach ($this->_vars['right_buttons'] as &$vo) {
            $vo['json'] = json_encode($vo);
        }
//        dump($this->_vars['right_buttons']);die;
        //定义唯一标识
        $extra_map = $this->_vars['extra_map'];
        $this->_vars['extra_map']['tableUniqueStr'] = $key;

        //构建搜索框
        $search = [];
        foreach ($this->_vars['search'] as $item) {
            if (!isset($item[2])) {
                throw new \Exception('搜索条件未定义type');
            }
            $types = explode(',', $item[2]);
            $data['key'] = $item[0] ?? '';
            $data['name'] = $item[1] ?? '';
            $data['type'] = $types[0];
            $data['index'] = isset($types[1]) ? $types[1] : '=';
            $data['value'] = $item[3] ?? '';
            $data['hasModel'] = $item[4] ?? '';
            $data['hasModelField'] = $item[5] ?? '';
            $search[] = $data;
        }
        $this->_vars['search'] = $search;
        //缓存相关内容
        $tableCache->setData([
            'search'    => $this->_vars['search'],
            'extra_map' => $extra_map,
            'census'    => $this->_vars['census']
        ], $key);
        //构建新增/编辑页面
        $tableCache->setModify($this->_vars['columns'], $key, $cache);
        //附加公共tpl
        $path = app()->getAppPath() . '/tpl/';
        foreach (['common'] as $v) {
            $this->_vars['extra_html'] .= View::fetch($path . $v . '.tpl', $this->_vars);
        }

        return View::fetch($template ?: $tableCache->getView(), $this->_vars);
    }


    public function addColumn($array = [])
    {
        $array['align'] = 'center';
        $this->_vars['columns'][] = $array;
        return $this;
    }

    public function getAllColumn($field = '')
    {
        return $field ? $this->_vars[$field] : $this->_vars;
    }

    public function addRightButton($type = '', $attribute = [])
    {
        $tableUniqueStr = isset($attribute['tableUniqueStr']) ? $attribute['tableUniqueStr'] : Builder::TableCache()->getMethodUrl();
        $s_nav = request()->nav['s_nav'];
        if (strrpos($s_nav, "列表")) {
            $unity_title = substr($s_nav, 0, strrpos($s_nav, "列表"));
        } else if (strrpos($s_nav, "管理")) {
            $unity_title = substr($s_nav, 0, strrpos($s_nav, "管理"));
        } else {
            $unity_title = $s_nav;
        }
        switch ($type) {
            case 'edit':
                $btn_attribute = [
                    'type'        => 'edit',
                    'title'       => '编辑',
                    'unity_title' => '编辑' . $unity_title,
                    'icon'        => '',
                    'class'       => 'layui-btn layui-btn-sm',
                    'url'         => url('edit', ['tableUniqueStr' => $tableUniqueStr])->build(),
                    'back_url'    => urlencode(request()->url())
                ];
                break;
            case 'delete':
                $class = isset($attribute['class']) ? $attribute['class'] : 'danger';
                $btn_attribute = [
                    'type'        => 'delete',
                    'title'       => '删除',
                    'unity_title' => $unity_title,
                    'icon'        => '',
                    'class'       => 'layui-btn layui-btn-sm layui-btn-' . $class,
                    'url'         => url('delete', ['tableUniqueStr' => $tableUniqueStr])->build()
                ];
                break;
            default:
                $class = isset($attribute['class']) ? $attribute['class'] : 'normal';
                $btn_attribute = [
                    'type'        => $type,
                    'title'       => '自定义按钮',
                    'unity_title' => $unity_title,
                    'icon'        => '',
                    'class'       => 'layui-btn layui-btn-sm layui-btn-' . $class,
                    'url'         => url('delete')->build(),
                    'back_url'    => urlencode(request()->url())
                ];
                break;
        }
        if (isset($attribute['size'])) {
            $size = explode(',', isset($attribute['size']) ? $attribute['size'] : '600,800');
            $btn_attribute['width'] = $size[0];
            $btn_attribute['height'] = isset($size[1]) ? $size[1] : '';
        }
        if ($attribute && is_array($attribute)) {
            if (isset($attribute['url']) && $attribute['url']) {
                $need = strpos($attribute['url'], '?') ? '&' : '?';
                $attribute['url'] .= $need . 'tableUniqueStr=' . $tableUniqueStr;
            }
            if (isset($attribute['class']) && $attribute['class']) {
                $attribute['class'] = 'layui-btn layui-btn-sm layui-btn-' . $attribute['class'];
            }
            $btn_attribute = array_merge($btn_attribute, $attribute);
        }
        $this->_vars['right_buttons'][] = $btn_attribute;
        return $this;
    }


    public function addRightButtons($buttons = [])
    {
        if (request()->admin->is_lock && !empty($buttons)) {
            $buttons = is_array($buttons) ? $buttons : explode(',', $buttons);
            foreach ($buttons as $key => $value) {
                if (is_numeric($key)) {
                    $this->addRightButton($value);
                } else {
                    $this->addRightButton(trim($key), $value);
                }
            }
        }
        return $this;
    }


    public function addTopButton($type = '', $attribute = [])
    {
        $tableUniqueStr = isset($attribute['tableUniqueStr']) ? $attribute['tableUniqueStr'] : Builder::TableCache()->getMethodUrl();
        if (isset($attribute['class'])) {
            $attribute['class'] = 'layui-btn layui-btn-' . $attribute['class'] . ' layui-btn-sm';
        }
        switch ($type) {
            // 新增按钮
            case 'add':
                $s_nav = request()->nav['s_nav'];
                if (strrpos($s_nav, "列表")) {
                    $unity_title = substr($s_nav, 0, strrpos($s_nav, "列表"));
                } else if (strrpos($s_nav, "管理")) {
                    $unity_title = substr($s_nav, 0, strrpos($s_nav, "管理"));
                } else {
                    $unity_title = $s_nav;
                }
                // 默认属性
                $btn_attribute = [
                    'title'       => '添加',
                    'unity_title' => '添加' . $unity_title,
                    'icon'        => 'layui-icon-add-circle-fine',
                    'class'       => 'layui-btn layui-btn-normal layui-btn-sm',
                    'onclick'     => 'buttons.add($(this))',
                    'href'        => url('add', ['tableUniqueStr' => $tableUniqueStr])->build(),
                    'back_url'    => urlencode(request()->url())
                ];
                break;
            // 批量删除按钮
            case 'deleteAll':
                // 默认属性
                $btn_attribute = [
                    'title'   => '批量删除',
                    'icon'    => 'layui-icon layui-icon-delete',
                    'class'   => 'layui-btn layui-btn-danger layui-btn-sm',
                    'href'    => url('delete', ['tableUniqueStr' => $tableUniqueStr])->build(),
                    'onclick' => 'buttons.removeAll($(this))'
                ];
                break;

            // 导出按钮
            case 'export':
                // 默认属性
                $btn_attribute = [
                    'title'   => '导出',
                    'icon'    => 'layui-icon-export',
                    'class'   => 'layui-btn layui-bg-cyan layui-btn-sm',
                    'href'    => url('export', request()->param()),
                    'onclick' => 'buttons.exportExcel($(this))'
                ];
                break;
            // 自定义按钮
            default:
                $class = isset($attribute['class']) ? $attribute['class'] : 'danger';
                $onclick = '';
                if (isset($attribute['event'])) {
                    $onclick = 'common.' . $attribute['event'] . '($(this))';
                }
                // 默认属性
                $btn_attribute = [
                    'title'    => isset($attribute['title']) ? $attribute['title'] : '',
                    'icon'     => isset($attribute['icon']) ? $attribute['icon'] : '',
                    'class'    => 'layui-btn layui-btn-sm layui-btn-' . $class,
                    'onclick'  => $onclick,
                    'url'      => isset($attribute['url']) ? $attribute['url'] : '',
                    'back_url' => urlencode(request()->url()),
                ];
                break;
        }
        if (isset($attribute['size'])) {
            $size = explode(',', isset($attribute['size']) ? $attribute['size'] : '600,800');
            $btn_attribute['width'] = $size[0];
            $btn_attribute['height'] = isset($size[1]) ? $size[1] : '';
        }
        // 合并自定义属性
        if ($attribute && is_array($attribute)) {
            $btn_attribute = array_merge($btn_attribute, $attribute);
        }
        $this->_vars['top_buttons'][] = $btn_attribute;
        return $this;
    }


    public function addTopButtons($buttons = [])
    {
        if (request()->admin->is_lock && !empty($buttons)) {
            $buttons = is_array($buttons) ? $buttons : explode(',', $buttons);
            foreach ($buttons as $key => $value) {
                if (is_numeric($key)) {
                    // key为数字则直接添加一个按钮
                    $this->addTopButton($value);
                } else {
                    // key不为数字则需设置属性，去除前后空格
                    $this->addTopButton(trim($key), $value);
                }
            }
        }
        return $this;
    }

    /**
     * 添加开关绑定栏
     * @param array $tool 开关组
     *                    例如：['name'=>'status','pk'=>'id','text'=>'锁定|正常']
     * @return $this
     */
    public function addSwitchTool($tool = [])
    {
        if (!empty($tool)) {
            $this->_vars['switch_tool'] = array_merge($this->_vars['switch_tool'], $tool);
        }
        return $this;
    }

    /**
     * 添加开关绑定栏
     * @param array $tool 开关组
     *                    例如：['name'=>'status','pk'=>'id','text'=>'锁定|正常']
     * @return $this
     */
    public function addSortTool($tool = [])
    {
        if (!empty($tool)) {
            $this->_vars['sort_tool'] = array_merge($this->_vars['sort_tool'], $tool);
        }
        return $this;
    }


    /**
     * 额外JS代码，
     * @param array $url
     */
    public function addJsUrl($url = [])
    {
        $this->_vars['js_url'] = $url;
        return $this;
    }

    /**
     * 设置是否开启合计行
     * @param string $bol => 'true' or 'false'
     * @return $this
     */
    public function setTotalRaw($bol = 'false')
    {
        $this->_vars['totalRow'] = $bol;
        return $this;
    }


    /**
     * 添加初始查询条件
     * @param array $map
     * @return $this
     */
    public function addExtraMap($map = [])
    {
        $this->_vars['extra_map'] = $map;
        return $this;
    }


    /**
     * 额外html代码
     * @param array $html
     * @return $this
     */
    public function addExtraHtml($tpl = [])
    {
        if (empty($tpl)) return $this;
        $path = app()->getAppPath() . '/tpl/';
        $html = '';
        //格式化右侧按钮
        foreach ($this->_vars['right_buttons'] as &$vo) {
            $vo['json'] = json_encode($vo);
        }
        View::assign($this->_vars);
        foreach ($tpl as $v) {
            $html .= View::fetch($path . $v . '.tpl');
        }
        $this->_vars['extra_html'] = $html;
        return $this;
    }


    /**
     * @param $model - model类或者controller
     * @param $method - 执行方法 - 必须为静态方法
     * @return $this
     * 添加统计信息
     */
    public function addCensus($model = '', $method = '')
    {
        if ($model && $method) {
            $this->_vars['census'] = [
                'model'  => $model,
                'method' => $method
            ];
        }
        return $this;
    }

    /**
     * @param $data - 搜索内容
     * @return $this
     * 原点 2023年1月17日15:41:02 设置搜索内容
     */
    public function addSearch(array $data = [], bool $time = true)
    {
        if ($time) {
            $data = array_merge([['create_time', '时间', 'time']], $data);
        }
        if ($data && is_array($data)) {
            $this->_vars['search'] = $data;
        }
        return $this;
    }

    /**
     * @param $model
     * @param $pk
     * @param $bar
     * @return Table
     * @throws Exception
     * 原点 2023年7月6日18:04:32 根据表结构自动构建
     */
    public function autoStructure($model, $pk = 'id', $bar = '', $cache = true, $check = true)
    {
        try {
            $tableName = (new $model())->getName();

            if (!env('APP_DEBUG') && $cache) {
                $_this = Cache::get('autoStructure_' . $tableName);
                if ($_this) return $_this;
            }
            $list = Db::query("SHOW FULL COLUMNS FROM " . $tableName);
            $_this = Builder::Table();
            if($check){
                $_this->addColumn(['type' => 'checkbox', 'title' => '全选', 'fixed' => 'left']);
            }
            $sort = [];
            $switch = [];
            foreach ($list as $item) {
                $analysisAll = TableCache::analysisComment($item['Comment']);
                if (!empty($analysisAll['hide'])) continue;
                $column = [
                    'field' => $item['Field']
                ];
                foreach ($analysisAll as $key => $value) {
                    if (!$value) continue;
                    if ($key == 't') {
                        if ($value == 2) {
                            $sort[] = ['name' => $item['Field'], 'pk' => $pk, 'url' => url('update')->build()];
                            $column['width'] = 120;
                        } else if ($value == 3) {
                            $switch[] = ['name' => $item['Field'], 'pk' => $pk, 'text' => '开启|关闭'];
                            $column['width'] = 120;
                        }
                    } else {
                        $column[$key] = $value;
                    }

                }
                if (isset($column['width'])) {
                    $column['width'] = intval($column['width']);
                }

                if ($item['Field'] == 'id') $column['width'] = 80;
                $_this->addColumn($column);
            }
            if (!empty($sort)) {
                $_this->addSortTool($sort)->addSwitchTool($switch);
            }
            if (!empty($switch)) {
                $_this->addSwitchTool($switch);
            }
            if ($bar) {
                $bars = explode(',', $bar);
                $_this->addColumn(['fixed' => 'right', 'title' => '操作', 'align' => 'center', 'toolbar' => '#' . $bars[0], 'width' => intval($bars[1])]);
            }
            if (!env('APP_DEBUG') && $cache) Cache::set('autoStructure_' . $tableName, $_this);

            return $_this;
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

}
